package  
{
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import org.flixel.*;
	import org.flixel.plugin.photonstorm.*;
	import org.flixel.plugin.photonstorm.BaseTypes.Bullet;
	
	/**
	 * ...
	 * @author le-ray_y
	 */
	public class Game extends FlxState 
	{
		//************************************************************************
		//** 							VARIABLES								**
		//************************************************************************
		
		// UI
		private var _ui:UI;
		
		// Background
		[Embed(source = '../../Assets/bg.jpg')]
		private var _backGroundClass:Class;
		private var _backGround:FlxSprite;
		
		// Tilemap for Collisions
		private var _collisionMap:FlxTilemap;
		
		// Timer
		private var _timer:Timer;
		
		// Enemy Array
		private var _enemyArray:FlxGroup;
		
		// Weapon
		private var _weapon:FlxWeapon;
		[Embed(source = '../../Assets/carotte.png')]
		private var _bulletGraph:Class;
		private var _enemyLaunched:Boolean = false;
		
		// Oil
		private var _oil:Oil;
		private var _poison:Poison;
		private var _rabbit:Rabbit;
		
		//************************************************************************
		//** 							FUNCTIONS								**
		//************************************************************************
		
		// CREATE
		override public function create():void
		{
			// Framerate
			FlxG.framerate = 50;
			FlxG.flashFramerate = 50;
			
			//	Enable the plugin - you only need do this once in your State (unless you destroy the plugin)
			if (FlxG.getPlugin(FlxMouseControl) == null)
			{
				FlxG.addPlugin(new FlxMouseControl);
			}
			
			// Background
			_backGround = new FlxSprite(0, 0, _backGroundClass);
			this.add(_backGround);
			
			// Oil
			_oil = new Oil(538, 296);
			this.add(_oil);
			
			// Poison
			_poison = new Poison(-100, -100);
			this.add(_poison);
			
			// Tower
			Global.tower = new Tower(800 - 219, 96);
			this.add(Global.tower);
			
			// Enemy Timer
			_timer = new Timer(1000, 0);
			_timer.start()
			_timer.addEventListener(TimerEvent.TIMER, timerlaunchEnemy);
			
			/*// Arrows Timer
			_timer = new Timer(1000, 0);
			_timer.start()
			_timer.addEventListener(TimerEvent.TIMER, timerlaunchArrows);
			*/
			
			// Enemy Array & Creation
			Global.enemies = new FlxGroup();
			this.add(Global.enemies);
			makeEnemies(10);
			
			/*// Enemy Healthbar Array
			_healthbarArray = new Array();*/
			
			// Goal Weapon
			_weapon = new FlxWeapon("bow", Global.tower);
			_weapon.makeImageBullet(500, _bulletGraph, 8, 8);
			_weapon.setBulletOffset(0, 225);
			_weapon.setBulletSpeed(250);
			_weapon.setBulletGravity(0, 400);
			_weapon.setFireRate(10);
			this.add(_weapon.group);
			
			// Inits ALL the UI elements!!!!
			setUI();
			
			
		}
		
		private function makeEnemies(value:Number):void 
		{
			for (var i:Number = 0; i < value; i++)
			{
				var enemy:Enemy = new Enemy(-50, 515 - 37 / 2, 100, 50);
				Global.enemies.add(enemy);
			}
		}
		
		public function getFreeEnemy():Enemy 
		{
			var result:Enemy = null;
			
			if (Global.enemies == null || Global.enemies.length == 0)
			{
				throw new Error("Game.as cannot launch an enemy until one has been created via a call to makeEnemies");
				return null;
			}
			
			for each (var enemy:Enemy in Global.enemies.members)
			{
				if (enemy.exists == false)
				{
					result = enemy;
					break;
				}
			}
			return result;
		}
		
		public function launchEnemy():void 
		{
			var currentEnemy:Enemy;
			
			currentEnemy = getFreeEnemy();
			
			if (currentEnemy == null)
			{
				trace ("No enemies available");
			}
			else
			{
				currentEnemy.reset(-50, 515 - 37 / 2);
			}
		}
		
		private function setUI():void 
		{
			_ui = new UI();
			this.add(_ui);
			
			// Adds all buttons and ui graphs
			_ui.add();
			
			_ui.test();
		}
		
		private function timerlaunchArrows(e:TimerEvent):void 
		{
			launchArrows();
		}
		
		private function timerlaunchEnemy(e:TimerEvent):void 
		{
			//launchEnemy();
		}
		
		override public function update():void
		{
			super.update();
			
			// Launch Enemy
			if (FlxG.keys.justPressed("SPACE"))
			{
				launchEnemy();
			}
			
			// Bowmen
			if (FlxG.keys.justPressed("V"))
			{
				launchArrows();
			}
			
			// Armor/Health Upgrade
			if (FlxG.keys.justPressed("A"))
			{
				upgradeTowerHealth();
			}
			
			// Regen Upgrade
			if (FlxG.keys.justPressed("Z"))
			{
				upgradeTowerRegen();
			}
			
			// Spine Upgrade
			if (FlxG.keys.justPressed("E"))
			{
				upgradeTowerSpine();
			}
			
			// Bow Upgrade
			if (FlxG.keys.justPressed("R"))
			{
				upgradeTowerBow();
			}
			
			// Oil Spill Upgrade
			if (FlxG.keys.justPressed("S"))
			{
				_oil.play("spill");
			}
			
			// Rabbit Upgrade
			if (FlxG.keys.justPressed("L"))
			{
				_rabbit = new Rabbit(815, 505, 100, 50);
				this.add(_rabbit);
			}
			
			/*// Poison Upgrade
			if (FlxG.keys.justPressed("D"))
			{
				_poison.x = FlxG.mouse.x;
				_poison.y = FlxG.mouse.y;
				_poison.play("reticle");
				
				
				trace (FlxG.mouse.x, FlxG.mouse.y);
			}
			
			if (FlxG.keys.justPressed("F"))
			{
				_poison.play("poison");
			}*/
			
			// Tower Damage
			if (FlxG.keys.justPressed("Q"))
			{
				damageTower(5);
			}
			
			/*******************
			** Collision handler
			********************/
			// Arrows and enemies
			FlxG.collide(_weapon.group, Global.enemies, onArrowCollide);
			//FlxG.overlap(_enemyArray, _tower, onEnemyTowerCollide);
			
			if (Global.enemies.getFirstAlive() != null)
			{
				for (var i:Number = 0; i < Global.enemies.length; i++)
				{
					if (FlxCollision.pixelPerfectCheck(Global.enemies.members[i], Global.tower))
					{
						onEnemyTowerCollide(Global.enemies.members[i], Global.tower);
					}
					
					if (FlxCollision.pixelPerfectCheck(Global.enemies.members[i], _oil))
					{
						onEnemySpillCollide(Global.enemies.members[i], _oil);
					}
				}
			}
		}
		
		private function onEnemyRabbitCollide(enemy:Enemy, rabbit:Rabbit):void 
		{
			if (enemy.alive)
			{
				enemy.velocity.x = enemy.velocity.y = 0;
				enemy.stopFollowingPath();
				enemy.play("attackRabbit");
			}
		}
		
		private function onEnemyTowerCollide(enemy:Enemy, tower:Tower):void 
		{
			if (enemy.alive)
			{
				enemy.velocity.x = enemy.velocity.y = 0;
				enemy.stopFollowingPath();
				enemy.play("attack");
			}
		}
		
		private function onEnemySpillCollide(enemy:Enemy, oil:Oil):void 
		{
			if (enemy.alive)
			{
				var tmp:Number = Number(_ui._score.text);
				
				_ui._score.text =  String(tmp + 10);
			}
			enemy.alive = false;
		}
		
		private function onArrowCollide(obj1:Bullet, obj2:Enemy):void 
		{
			obj1.kill();
			if (obj2.alive)
			{
				var tmp:Number = Number(_ui._score.text);
				
				_ui._score.text =  String(tmp + 10);
			}
			obj2.alive = false;
		}
		
		private function damageTower(enmLvl:Number):void 
		{
			Global.tower.health -= 10 * enmLvl;
		}
		
		// Upgrade Tower Health
		private function upgradeTowerHealth():void 
		{
			Global.tower._healthLevel++;
			Global.tower.health += 500 * Global.tower._healthLevel;
			Global.tower._maxHealth += 500 * Global.tower._healthLevel;
			
			// Update hp bar in the ui
			_ui._hpBar.setRange(0, Global.tower._maxHealth);
			
			trace (Global.tower._healthLevel + " " + Global.tower.health + " " + Global.tower._maxHealth);
		}
		
		// Upgrade Tower Regen
		private function upgradeTowerRegen():void 
		{
			Global.tower._regenLevel++;
			
			trace (Global.tower._regenLevel + " " + 5 * Global.tower._regenLevel);
		}
		
		// Upgrade Tower Spine
		private function upgradeTowerSpine():void 
		{
			Global.tower._spineLevel++;
			
			trace (Global.tower._spineLevel + " " + Global.tower._spineLevel * 10);
		}
		
		// Upgrade Tower Bow
		private function upgradeTowerBow():void 
		{
			Global.tower._bowLevel++;
			_weapon.setFireRate(100);
		}
		
		private function launchArrows():void 
		{
			for (var i:Number = 0; i < Global.enemies.length; i++)
				{
					if (FlxVelocity.distanceBetween(Global.tower, Global.enemies.members[i]) <= 400)
					{
						//_weapon.fireAtTarget(_enemyArray.members[i]);
						_weapon.setBulletSpeed(100 + 250 * Math.random());
						_weapon.fireFromAngle( -135);
					}
				}
		}
	}

}